package com.bruce.asurada.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.nacos.common.utils.StringUtils;
import com.bruce.asurada.common.Result;
import com.bruce.asurada.common.constants.TokenConstants;
import com.bruce.asurada.dto.LoginResponseDto;
import com.bruce.asurada.handler.WebSocketHandler;
import com.bruce.asurada.common.dto.*;
import com.bruce.asurada.constants.SSOConstants;
import com.bruce.asurada.service.SsoClientService;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import jakarta.servlet.http.Cookie;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * SSO控制器 - 统一处理UI展示和API接口
 */
@RestController
@RequestMapping("/asurada")
public class AsuradaController {

    private static final Logger logger = LoggerFactory.getLogger(AsuradaController.class);

    @Autowired
    private SsoClientService ssoClientService;
 
    @Autowired
    private WebSocketHandler webSocketHandler;

    /**
     * 账号密码登录 获取授权码
     */
    @PostMapping("/login")
    @ResponseBody
    public Result<String> login(@RequestBody UserLoginDto loginDto, HttpServletResponse response) {
        logger.info("用户登录请求: {}", loginDto.getAccount());
        
        try {
            String authCode = ssoClientService.getAuthCode(loginDto);
            if (StringUtils.isBlank(authCode)) {
               return Result.error("登录失败，原因：授权码为空");
            }
            return Result.success(authCode);
        } catch (Exception e) {
            logger.error("登录过程中发生异常: {}", e.getMessage(), e);
            return Result.error("登录失败，请稍后重试");
        }
    }

    /**
     * 通过授权码获取令牌
     * @param loginDto
     * @param response
     * @return
     */
    @PostMapping("/token")
    public Result<TokenDTO> getToken(@RequestBody UserLoginDto loginDto,HttpServletRequest request,HttpServletResponse response) {
        try{
            String authCode = extractAuthCodeFromRequest(request);
            TokenDTO tokenDTO = ssoClientService.getToken(loginDto,authCode);
            return Result.success(tokenDTO);
        }catch (Exception e) {
            logger.error("登录过程中发生异常: {}", e.getMessage(), e);
            return Result.error("登录失败，请稍后重试");
        }
    }
    

    /**
     * 验证码登录
     * @param loginDto
     * @param response
     * @return
     */
    @GetMapping("/sendPhoneCode")
    @ResponseBody
    public Result<Void> sendPhoneCode(@RequestParam(required = true, value = "phone") String phone){
       return ssoClientService.sendPhoneCode(phone) ;
    }

    /**
     * 验证码登录
     * @param loginDto
     * @param response
     * @return
     */
    @PostMapping("/loginByPhoneAndCode")
    @ResponseBody
    public Result<LoginResponseDto> loginByPhoneAndCode(@RequestBody PhoneCodeLoginDTO loginDto, HttpServletResponse response){
       return ssoClientService.loginByPhoneAndCode(loginDto) ;
    }


    /**
     * 登出接口
     */
    @PostMapping("/logout")
    @ResponseBody
    public Result<Void> logout(HttpServletRequest request, HttpServletResponse response) {
        try {
            TokenDTO tokenDTO = extractTokenFromRequest(request);
            String username = request.getParameter("username");
            if(StringUtils.isBlank(username)){
                return Result.error("未提供用户名");
            }
            if (tokenDTO != null) {
                ssoClientService.logout(tokenDTO);
            }
            webSocketHandler.closeUserSession(username);
            logger.info("用户登出成功");
            return Result.success();
        } catch (Exception e) {
            logger.error("登出过程中发生异常: {}", e.getMessage(), e);
            return Result.error("登出失败");
        }
    }


    /**
     * 刷新令牌接口
     */
    @PostMapping("/refresh")
    @ResponseBody
    public Result<TokenDTO> refreshToken(HttpServletRequest request, HttpServletResponse response) {
        try {
            TokenDTO tokenDTO = extractTokenFromRequest(request);
            if (tokenDTO == null) {
                return Result.error("未找到令牌");
            }
            
            TokenDTO refreshTokenDTO = ssoClientService.refreshToken(tokenDTO.getRefreshToken());
            return Result.success(refreshTokenDTO);
        } catch (Exception e) {
            logger.error("刷新令牌过程中发生异常: {}", e.getMessage(), e);
            return Result.error("刷新令牌失败");
        }
    }



    /**
     * 验证令牌接口
     */
    @GetMapping("/verify")
    @ResponseBody
    public Result<UserInfoDto> verifyToken(HttpServletRequest request) {
        try {
            TokenDTO tokenDTO = extractTokenFromRequest(request);
            if (tokenDTO == null) {
                return Result.error("未找到令牌");
            }
            UserInfoDto userInfoDto = ssoClientService.verifyToken(tokenDTO.getAccessToken());
            return Result.success(userInfoDto);
        } catch (Exception e) {
            logger.error("验证令牌过程中发生异常: {}", e.getMessage(), e);
            return Result.error("验证令牌失败");
        }
    }

    /**
     * 检查登录状态接口
     */
    @GetMapping("/status")
    @ResponseBody
    public Result<Boolean> checkLoginStatus(HttpServletRequest request) {
        try {
            TokenDTO tokenDTO = extractTokenFromRequest(request);
            UserInfoDto userInfoDto = ssoClientService.verifyToken(tokenDTO.getAccessToken());
            return Result.success(userInfoDto != null);
        } catch (Exception e) {
            logger.error("检查登录状态过程中发生异常: {}", e.getMessage(), e);
            return Result.success(false);
        }
    }

    // /**
    //  * SSO回调处理
    //  */
    // @GetMapping("/callback")
    // public String callback(@RequestParam(required = false) String token, 
    //                       @RequestParam(required = false) String error,
    //                       HttpServletResponse response) {
    //     if (error != null) {
    //         logger.warn("SSO回调返回错误: {}", error);
    //         return "redirect:/login?error=" + error;
    //     }
        
    //     if (token != null) {
    //         // 设置令牌Cookie
    //         Cookie cookie = new Cookie(TOKEN_COOKIE_NAME, token);
    //         cookie.setHttpOnly(true);
    //         cookie.setPath("/");
    //         cookie.setMaxAge(7 * 24 * 60 * 60); // 7天
    //         response.addCookie(cookie);
            
    //         logger.info("SSO回调成功，令牌已设置");
    //         return "redirect:/";
    //     }
        
    //     logger.warn("SSO回调缺少必要参数");
    //     return "redirect:/login?error=invalid_callback";
    // }

    // ==================== 私有方法 ====================


    /**
     * 从请求中提取授权码
     */
    private String extractAuthCodeFromRequest(HttpServletRequest request) throws Exception {
        
        // 从请求头中获取授权码
        String getRequ = request.getHeader("X-Auth-Code") ;
        if(StringUtils.isBlank(getRequ)){
            throw new Exception("未在请求头中找到授权码") ;
        }
        return getRequ ;
    }


    /**
     * 从Request请求中提取令牌
     * @param request
     * @return
     * @throws Exception
     */
    private TokenDTO extractTokenFromRequest(HttpServletRequest request) throws Exception {
        return TokenDTO.builder().accessToken(getAccessToken(request))
        .refreshToken(request.getHeader("X-Refresh-Token"))
        .imSessionToken(request.getHeader("X-Im-access-Token"))
        .imAccessToken(request.getHeader("X-Im-session-Token"))
        .build();
    }



    /**
     * 从请求中获取令牌
     */
    private String getAccessToken(HttpServletRequest request) {
        // 从Authorization头获取
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}
